import csv, StringIO, logging
from google.appengine.ext import webapp
from process_data import processUploadedCompaction
from django.utils import simplejson
from ft_table import FtTable
import dlz_config as dc
from google.appengine.api import users
from record import Record
from google.appengine.api import memcache

import model, urllib2
from errors import *

def formatTestNumberFields(record):
    '''
    format the number fields to %.1f format
    '''
    for fld in 'wet_unit_weight    moisture_content moisture_contentfield    dry_unit_weight dry_unit_weight_field one_point_moisture    moisture_contentlab    dry_unit_weight_lab    max_dry_unit_weight    optimum_moisture_content    specified    obtained'.split():
        if record.values.get(fld):
            try:
                record[fld] = '%.1f' % float(record[fld])
            except:
                pass

def insert_record(ft, r, t):
    try:
        record = Record(ft)
        for k, v in r.items():
            if v:
                record[k] = v
        formatTestNumberFields(record)
        record.insert(t)
    except DLZError, de:
        s = model.SqlRequest()
        if t: s.transaction_ref = t
        if de.title:
            s.description = de.title
        s.sql = de.message
        s.status = 'new'
        s.put()
        logging.fatal('Failed to insert record:%s' % str(s.sql))



def insert_records_into_ft(records, tableid, table_name='The table'):
    t = model.Transaction()
    t.description = 'Insert records into fusion table : %s' % table_name
    t.put()
    for r in records:
        ID = r['ID']
        ft = FtTable(None, None, tableid)
        sql = "select rowid from %s where ID = '%s'" % (tableid, ID)
        result = ft.SqlQuery(sql)
        
        if len(result)>0:
            rowid = result[0].get('rowid')
            logging.info('%s already has a record (rowid: %s) with the ID of %s' % (table_name, rowid, ID))
        else:
            insert_record(ft, r, t)
    


def insert_compaction_test(records):
    '''
    insert records into compaction_test table
    '''
    #make sure nothing is from the cache
    memcache.flush_all()
    tableid = int(dc.get('DLZ_COMPACTION_TEST')['ft_table_id'])
    insert_records_into_ft(records, tableid, table_name='compaction_test')
#    t = model.Transaction()
#    t.description = 'Insert records into compaction_test.'
#    t.put()
#    for r in records:
#        ID = r['ID']
#        ft = FtTable(None, None, tableid)
#        sql = "select rowid from %s where ID = '%s'" % (tableid, ID)
#        result = ft.SqlQuery(sql)
#        
#        if len(result)>0:
#            rowid = result[0].get('rowid')
#            logging.info('compaction_test already has a record (rowid: %s) with the ID of %s' % (rowid, ID))
#        else:
#            insert_record(ft, r, t)
#    

def insert_compaction_form(records):
    '''
    insert records into compaction_form table
    '''
    #make sure nothing is from the cache
    memcache.flush_all()
    #see if the ID is already exist
    tableid = int(dc.get('DLZ_COMPACTION_FORM')['ft_table_id'])
    insert_records_into_ft(records, tableid, table_name='compaction_form')
#    t = model.Transaction()
#    t.description = 'Insert records into compaction_form.'
#    t.put()
#    for r in records:
#        ID = r['ID']
#        ft = FtTable(None, None, tableid)
#        sql = "select rowid from %s where ID = '%s'" % (tableid, ID)
#        try:
#            result = ft.SqlQuery(sql)
#        except:
#            result = []
#            logging.info('Failed to query the table, possible insert duplicate record into compaction_test. ID=%s' % ID)
#            pass
#        if len(result)>0:
#            rowid = result[0].get('rowid')
#            logging.info('compaction_form already has a record (rowid: %s) with the ID of %s' % (rowid, ID))
#        else:
#            insert_record(ft, r, t)
    

def update_compaction_test(records, tableid, change_table_id=None):
    '''
    update the compaction_test table with the records
    '''
    #make sure nothing is from the cache
    memcache.flush_all()
    #check if the file  format is OK
    row1, row2 = dc.get_dlz_compaction_schema()
    header = records[0]
    messages = []
    #check if fields are correct
    for fld in header:
        if fld in row1:
            pass
        else:
            messages.append('Field "%s" is not a system defined field.' % fld)
            logging.warning('Field "%s" is not a system defined field.' % fld)
    for fld in row1:
        if fld in header:
            pass
        else:
            logging.warning('Field "%s" is not in uploaded table' % fld)
            messages.append ('Field "%s" is not in uploaded table' % fld)
    
    #check if rowid is present
    if 'rowid' in header:
        pass
    else:
        logging.fatal('rowid is not found in uploaded table')
        messages.append('rowid is not found in uploaded table')
        return {'success': False, 'message': messages}
    logging.info('Uploading CSV file to table: %s' % tableid)
    data = records[2:]
    ft = FtTable(None, None, tableid)
    #add transaction
    t = model.Transaction()
    t.description = 'Update compaction_test using a Uploaded CSV file'
    t.owner = users.GetCurrentUser()
    t.put()
    
    
    for r_uploaded in data:
        #only update the testing form, project form is ignored.
        r_uploaded = dict(zip(header, r_uploaded))
        rowid = r_uploaded['rowid'].split('_')[0]
        try:
            r = Record(ft, rowid)
            for fld in header:
                if fld=='rowid':
                    pass
                else:
                    r[fld] = r_uploaded[fld]
            r.update(t)
            logging.info('update record success.')
        except DLZError, de:
            s = model.SqlRequest()
            if de.title:
                s.description = de.title
            s.sql = de.message
            if t: s.transaction_ref = t
            s.status = 'new'
            s.put()
            logging.info('update record failed.')
    

    
            
        
        
class UploadHandler(webapp.RequestHandler):
    def get(self):
        html = '''<form enctype="multipart/form-data" action="/upload" method="post">
                    <label>File:</label><input type="file" name="file" /><br/>
                    <label>File Type:</label><input type="text" name="file_type" value="csv" /><br/>
                    <label>Action:</label><input type="text" name="action" value="show" /><br/>
                    <input type="submit" value="Upload"/>
                </form>
'''
        self.response.out.write(html)
    
    def post(self):
        file_content = self.request.get('file')
        file_type = self.request.get('file_type')
        action = self.request.get('action')
        if file_type=='csv':
            results = self.upload_csv(file_content)
            return
        
        self.response.headers["Content-Type"] = "application/json"  
        self.response.out.write(simplejson.dumps({'result': {'file': 'download.csv'}, 'rows': str(results)}))
    
    def upload_csv(self, csv_file):
        '''pass a string of a csv file and parse it into json format'''
        fhandler = StringIO.StringIO(csv_file)
        reader = csv.reader(fhandler)
        results = []
        for l in reader:
            results.append(l)
        fhandler.close()
        
        result = update_compaction_test(results, int(dc.get('DLZ_COMPACTION_TEST')['ft_table_id']))
        self.response.headers["Content-Type"] = "application/json"
        self.response.out.write(simplejson.dumps(result))